﻿using FreeSql;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Furion.DatabaseAccessor
{
    /// <summary>
    /// 非泛型 FreeSql 仓储
    /// </summary>
    public partial class FreeSqlRepository : IFreeSqlRepository
    {
        /// <summary>
        /// 服务提供器
        /// </summary>
        private readonly IServiceProvider _serviceProvider;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serviceProvider">服务提供器</param>
        public FreeSqlRepository(
            IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TKey">主键类型</typeparam>
        /// <returns>仓储</returns>
        public virtual IFreeSqlRepository<TEntity, TKey> Change<TEntity, TKey>()
            where TEntity : class, new()
        {
            return _serviceProvider.GetService<IFreeSqlRepository<TEntity, TKey>>();
        }
    }

    /// <summary>
    /// FreeSql 泛型仓储
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public partial class FreeSqlRepository<TEntity> : FreeSqlRepository<TEntity, string>, IFreeSqlRepository<TEntity> where TEntity : class, new()
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="uowm"></param>
        /// <param name="freeSqlRepository"></param>
        public FreeSqlRepository(UnitOfWorkManager uowm, IFreeSqlRepository freeSqlRepository) : base(uowm, freeSqlRepository)
        {
        }
    }

    /// <summary>
    /// FreeSql 泛型仓储
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public partial class FreeSqlRepository<TEntity, TKey> : BaseRepository<TEntity, TKey>, IFreeSqlRepository<TEntity, TKey> where TEntity : class, new()
    {
        /// <summary>
        /// 非泛型 FreeSql 仓储
        /// </summary>
        private readonly IFreeSqlRepository _freeSqlRepository;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="uowm">工作单元</param>
        /// <param name="freeSqlRepository">非泛型 FreeSql 仓储</param>
        public FreeSqlRepository(UnitOfWorkManager uowm, IFreeSqlRepository freeSqlRepository) : base(uowm.Orm, null, null)
        {
            uowm.Binding(this);
            _freeSqlRepository = freeSqlRepository;
            DynamicDbContext = uowm.Orm;
            Ado = uowm.Orm.Ado;
        }

        /// <summary>
        /// 动态数据库上下文
        /// </summary>
        public virtual dynamic DynamicDbContext { get; }

        /// <summary>
        /// 原生 Ado 对象
        /// </summary>
        public virtual IAdo Ado { get; }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="expression">条件</param>
        /// <returns></returns>
        public long Count(Expression<Func<TEntity, bool>> expression)
        {
            Select.Where(expression).Count(out long total);
            return total;
        }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="expression">条件</param>
        /// <returns></returns>
        public virtual async Task<long> CountAsync(Expression<Func<TEntity, bool>> expression)
        {
            return await Select.Where(expression).CountAsync();
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public bool Any(Expression<Func<TEntity, bool>> expression)
        {
            return Select.Any(expression);
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> expression)
        {
            return await Select.AnyAsync(expression);
        }

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public TEntity Single(dynamic id)
        {
            return Select.WhereDynamic(id).ToOne();
        }

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<TEntity> SingleAsync(dynamic id)
        {
            return await Select.WhereDynamic(id).ToOneAsync();
        }

        /// <summary>
        /// 获取单条记录
        /// </summary>
        /// <typeparam name="TDto"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual Task<TDto> GetAsync<TDto>(TKey id)
        {
            return Select.WhereDynamic(id).ToOneAsync<TDto>();
        }

        /// <summary>
        /// 获取单条记录
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public virtual Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> exp)
        {
            return Select.Where(exp).ToOneAsync();
        }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual IFreeSqlRepository<TChangeEntity, string> Change<TChangeEntity>()
            where TChangeEntity : class, new()
        {
            return _freeSqlRepository.Change<TChangeEntity, string>();
        }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity">实体类型</typeparam>
        /// <typeparam name="TChangeKey">主键类型</typeparam>
        /// <returns>仓储</returns>
        public virtual IFreeSqlRepository<TChangeEntity, TChangeKey> Change<TChangeEntity, TChangeKey>()
            where TChangeEntity : class, new()
        {
            return _freeSqlRepository.Change<TChangeEntity, TChangeKey>();
        }
    }
}
